home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
Advanced I⁄O v2.3
/
Advanced i⁄o
/
arithm_modadapt.cc
< prev
next >
Wrap
Text File
|
1995-05-29
|
6KB
|
179 lines
// This may look like C code, but it is really -*- C++ -*-
/*
************************************************************************
*
* Adaptive Arithmetic Coding
* Adaptive model for the data source
*
* This is the implementation of the adaptive model based on the
* Input_Data_Model.
*
* The present model is tailored to coding node values of the Laplacian
* pyramid decomposition of gray-scale still images. The distribution of
* the values is found (see laplpyr_hist.lst) to be almost ideally
* modelled by the Lorentzian distribution with a very strong peak at
* 0. This apriori information is coded into the frequency tables. As
* symbols are processed, the frequency tables are updated (in the
* way it is described in the book "Text Compression" referred to
* elsewhere) to finely adjust the distribution. Note that re-scaling
* of the frequencies is carried out more frequently than it is really
* needed to prevent overflow in the coder. The reason is, rescaling of the
* model makes it gradually forget what happened long ago, and tunes in the
* model to the recent data. It makes sense if the ideal source model changes
* with the time. It is certainly the case in the Laplacian pyramid,
* where probability ditribution for different layers may be different.
*
* The program assumes the total no. of distinct input symbols
* (integers) is relatively small, so simple linear arrays can be used
* for storing and looking up the frequency tables.
*
* $Id: arithm_modadapt.cc,v 1.3 1993/06/24 14:54:07 oleg Exp oleg $
*
************************************************************************
*/
#pragma implementation "arithm_modadapt.h"
#include "arithm_modadapt.h"
#include "std.h"
/*
*------------------------------------------------------------------------
* Constructors and Destructors
*/
// Constructor
AdaptiveModel::AdaptiveModel(const Symbol lwb, const Symbol upb)
: symbol_lwb(lwb), symbol_upb(upb),
no_symbols(upb-lwb+1)
{
assure(no_symbols > 1,
"Bracketing interval for input symbols should include at least "
"two symbols");
allocate_model(no_symbols);
symbol_to_index = new Index[no_symbols];
// Note, indices range from 1 to EOF_index,
// but EOF_index maps to no symbol
index_to_symbol = new Symbol[no_symbols];
initialize_model();
}
// Destructor
AdaptiveModel::~AdaptiveModel()
{
assert( symbol_to_index != 0 && index_to_symbol != 0 );
delete [] symbol_to_index;
delete [] index_to_symbol;
}
// Initialize the model
void AdaptiveModel::initialize_model(void)
{
// Set up the index vs. symbol mapping such
// that symbol 0 would have index 1,
// symbol 1 - index 2, symbol -1 - index 3,
// etc.
register int i;
// Assume the symbol just in the middle is
// most likely to occur
register Symbol symbol = (symbol_lwb + symbol_upb)/2;
register Index index;
for(index=1,i=1; ;)
{
assert( symbol >= symbol_lwb && symbol <= symbol_upb );
symbol_to_index[symbol-symbol_lwb] = index;
index_to_symbol[index-1] = symbol;
if( !(++index <= no_symbols) )
break;
while( abs(i) < 2*no_symbols )
{
symbol += i;
i = ( i>0 ? -i-1 : -i+1 );
if( symbol <= symbol_upb && symbol >= symbol_lwb )
break;
}
assert( abs(i) < 2*no_symbols );
}
// Assign initial frequency counts
// according to Lorentzian ditribution
cum_frequencies[no_indices] = 0;
for(i=no_indices; i>0; i--)
{
frequencies[i] = ( i == 1 ? 10*no_symbols : i <= 10 ? 10 : 1 );
cum_frequencies[i-1] = cum_frequencies[i] + frequencies[i];
}
frequencies[0] = 0; // Must be zero to differ from freq[1]
}
/*
*------------------------------------------------------------------------
* Searching for index/symbol
*/
// Return the index of a given symbol
Index AdaptiveModel::get_index(const Symbol symbol) const
{
if( symbol < symbol_lwb || symbol > symbol_upb )
_error("Symbol %d is out of interval [%d,%d]",
symbol, symbol_lwb, symbol_upb);
return symbol_to_index[symbol-symbol_lwb];
}
// Return the symbol for a given index
Symbol AdaptiveModel::get_symbol(const Index index) const
{
if( index < 1 || index > no_symbols )
_error("Index %d is out of boundaries [1,%d]",index,no_symbols);
return index_to_symbol[index-1];
}
/*
*------------------------------------------------------------------------
* Update the adaptive model
* to account for occurence of a particular index
*/
void AdaptiveModel::update_model(const Index index)
{
if( total_cum_freq() >= Top_freq/4 ) // See if freq counts near their max
{ // /4 makes rescaling work more often
register int cum = 0; // If so, halve all the counts
register int i; // keeping them nonzero, and
for(i=no_indices; i>=0; i--) // recompute the cumulative counts
{
cum_frequencies[i] = cum;
cum += (frequencies[i] = (frequencies[i]+1) >> 1);
}
}
// Try to pull 'index' to the beginning
// of the freq. table, skipping symbols
// with the same freq.
register Lword * fp;
for(fp = &frequencies[index]; *fp == *(fp-1); fp--)
; // Note, freq[0] never = freq[1]
Index new_index = fp - frequencies; // Find a new position for the index
if( new_index < index ) // If the index is to move, update
{ // the translation tables
Symbol symbol_oind = index_to_symbol[index-1];
Symbol symbol_nind = index_to_symbol[new_index-1];
index_to_symbol[index-1] = symbol_nind;
index_to_symbol[new_index-1] = symbol_oind;
symbol_to_index[symbol_oind-symbol_lwb] = new_index;
symbol_to_index[symbol_nind-symbol_lwb] = index;
}
// Note, the increment is large enough,
const int update_inc = no_symbols/5 + 1; // since the count 1 acts like
// -Infinity
frequencies[new_index] += update_inc; // Increment the freq count for index
register Lword * cfp; // And update the cumulative counts
for(cfp=&cum_frequencies[new_index]; cfp>&cum_frequencies[0]; )
*--cfp += update_inc;
}